package controller

import (
	"fmt"
	"github.com/ethereum/go-ethereum/common/hexutil"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/gin-gonic/gin"
	"log"
	"src/req"
	"src/response"
	"src/utils"
	"strings"
)

/*
@date : 2024/8/30 14:09
@author : mie
@desc:
*/

func WalletConnectAuthRoute(api *gin.RouterGroup) {
	api.POST("/auth", func(c *gin.Context) {
		var ar req.AuthReq
		if err := c.ShouldBindJSON(&ar); err != nil {
			response.Fail(c, 500, utils.ValidateMsg(ar, err))
			return
		}
		message, signature, address := ar.Message, ar.Signature, ar.Account
		log.Printf("message : %v , sig: %s, address :%s", message, signature, address)
		// MetaMask prefixes the message with "\x19Ethereum Signed Message:\n32"
		prefix := fmt.Sprintf("\x19Ethereum Signed Message:\n%d", len(message))
		prefixedMessage := crypto.Keccak256Hash([]byte(prefix + message))
		signatureBytes, err := hexutil.Decode(signature)
		if err != nil {
			response.XFail(c, err.Error())
			return
		}
		// Ensure signature length is correct
		if len(signatureBytes) != 65 {
			response.XFail(c, "Invalid signature length")
			return
		}
		// Adjust the signature format if needed (the `v` value must be 27 or 28)
		if signatureBytes[64] != 27 && signatureBytes[64] != 28 {
			response.XFail(c, "invalid signature recovery id")
			return
		}
		signatureBytes[64] -= 27 // 将 v 值转换为 0 或 1
		// Recover the public key from the signature
		pubKey, err := crypto.SigToPub(prefixedMessage.Bytes(), signatureBytes)
		if err != nil {
			response.XFail(c, err.Error())
			return
		}
		// Derive the Ethereum address from the public key
		recoveredAddress := crypto.PubkeyToAddress(*pubKey).Hex()
		// Compare the recovered address with the provided address
		matches := strings.ToLower(recoveredAddress) == strings.ToLower(address)
		//data := map[string]interface{}{
		//	"address": address,
		//	"invalid": matches,
		//}
		if !matches {
			response.XFail(c, "invalid fail")
			return
		}
		response.Success(c, address)

	})
}
